import {accessKey,secretKey} from "./idAuthozation.js";
import  CryptoJS from "crypto-js";

function normalize(string, encodingSlash) {
  //链接规范化处理
  let kEscapedMap = {
    "!": "%21",
    "'": "%27",
    "(": "%28",
    ")": "%29",
    "*": "%2A",
  };

  if (string === null) {
    return "";
  }
  var result = encodeURIComponent(string);
  result = result.replace(/[!'\(\)\*]/g, function ($1) {
    return kEscapedMap[$1];
  });

  if (encodingSlash === false) {
    result = result.replace(/%2F/gi, "/");
  }

  return result;
}

function generateCanonicalUri(resources) {
  //生成规范路径
  let normalizedResourceStr = "/" + normalize(resources);
  
  return normalizedResourceStr;
}

function generateCanonicalQueryString(query) {
  //生成规范参数
  if (!query) {
    return ""
  }
  var queryList = query.split('&');
  console.log(queryList,' =>> queryList');
  let normalizedQueryList = [];
  for (let i = 0; i < queryList.length; i++) {
    let query = queryList[i].split('=');
    normalizedQueryList.push(
      normalize(query[0]) + "=" + normalize(query[1])
    );
  }
  normalizedQueryList.sort();
  return normalizedQueryList.join("&");
}

var g_signed_header = "";
function generateCanonicalHeaders(headerList,signedHeaders) {
  //生成规范请求头
  let defaultHeaders = ["host", "content-length", "content-type", "content-md5"];
  let keyStrList = []; //键名列表

  if (!signedHeaders) {
    console.log("generateCanonicalHeader: using default headers");
    for (let i = 0; i < defaultHeaders.length; i++) {
        keyStrList.push(defaultHeaders[i]);
    }

    for (let key in headerList) {
        if (key.toLowerCase().startsWith("x-bce-")) { //规范性过滤
            keyStrList.push(key.toLowerCase());
        }
    }
  } else {
    signedHeaders = signedHeaders.trim();
    keyStrList = signedHeaders.split(';');
    for (let i = 0; i < keyStrList.length; i++) {
        keyStrList[i] = keyStrList[i].toLowerCase(); //列表值小写
    }
    if (!keyStrList.includes("host")) {
        keyStrList.push("host");
    }
  }
  let usedHeaderStrList = [];
  for (let i = 0; i < keyStrList.length; i++) {
      let key = keyStrList[i];
      let value = headerList[key];//已填header 键和值
      console.log(key,":",value,' >检测');
      if (!value || value == undefined) { //有效性检验
          continue;
      }
      key = key.toLowerCase();
      value = value.trim();
      console.log(key,":",value,' >结果有效');
      usedHeaderStrList.push(normalize(key) + ":" + normalize(value));
  }

  usedHeaderStrList.sort();
  console.log(usedHeaderStrList,'  >> usedHeaderStrList');
  let usedHeaderKeys = [];
  usedHeaderStrList.forEach(function(item) {
      usedHeaderKeys.push(item.split(':')[0]);
  });
  console.log(usedHeaderKeys,'  >> usedHeaderKeys');
  let canonicalHeaderStr = usedHeaderStrList.join('\n');//已填header的键列表
  g_signed_header = usedHeaderKeys.join(';');//已填header键值对列表
  return canonicalHeaderStr;
}

function generateAuthorization(method,path,query,headerList,signedHeaders) {
  var timestamp = new Date().toISOString().replace(/\.\d+Z$/, "Z");
  let expirationInSeconds = (!expirationInSeconds) ? "1800" : expirationInSeconds.trim();
  var signingKeyStr = "bce-auth-v1/" + accessKey.trim() + "/" + timestamp + "/" + expirationInSeconds;
  let signingKey = CryptoJS.HmacSHA256(signingKeyStr, secretKey.trim());
    console.log("signing key: " + signingKey.toString());

  let canonicalUri = generateCanonicalUri(path);
    console.log("Canonical Uri: " + canonicalUri);

  let canonicalQueryString = generateCanonicalQueryString(query);
    console.log("Canonical Query string: " + canonicalQueryString);
  
  let canonicalHeaders = generateCanonicalHeaders(headerList,signedHeaders);
    console.log("Canonical Headers: \n" + canonicalHeaders);

  let canonicalRequest = method.toUpperCase() + "\n" + canonicalUri + "\n" + canonicalQueryString + "\n" + canonicalHeaders;
    console.log("Canonical Request: \n" + canonicalRequest);

  let signature = CryptoJS.HmacSHA256(canonicalRequest, signingKey.toString());
    console.log("Signature: " + signature.toString());

    
  let Authorization = signingKeyStr + "/" + g_signed_header + "/" + signature.toString();

  console.log("Authorization: " + Authorization);
    return Authorization;
}

export {generateCanonicalUri,generateCanonicalQueryString,generateCanonicalHeaders,generateAuthorization};
